/*************************************************************************//**
 *****************************************************************************
 * @file   const.h
 * @brief  
 * @author Forrest Y. Yu
 * @date   2005
 *****************************************************************************
 *****************************************************************************/

#ifndef	_ORANGES_CONST_H_
#define	_ORANGES_CONST_H_

#define __ORANGES_DEBUG__

/* errno  */
#define	OK		0
#define	E_UNKNOWN	1
#define	E_DEADLOCK	2

/* max() & min() */
#define	max(a,b)	((a) > (b) ? (a) : (b))
#define	min(a,b)	((a) < (b) ? (a) : (b))

/* Color */
/*
 * e.g. MAKE_COLOR(BLUE, RED)
 *      MAKE_COLOR(BLACK, RED) | BRIGHT
 *      MAKE_COLOR(BLACK, RED) | BRIGHT | FLASH
 */
#define BLACK	0x0	/* 0000 */
#define WHITE	0x7	/* 0111 */
#define RED	0x4	/* 0100 */
#define GREEN	0x2	/* 0010 */
#define BLUE	0x1	/* 0001 */
#define FLASH	0x80	/* 1000 0000 */
#define BRIGHT	0x08	/* 0000 1000 */
#define MAKE_COLOR(x,y)	((x<<4) | y) /* MAKE_COLOR(Background,Foreground) */

/* magic chars used by `printx' */
#define MAG_CH_PANIC	'\002'
#define MAG_CH_ASSERT	'\003'

/* How many descriptors in GDT and IDT */
#define	GDT_SIZE	128
#define	IDT_SIZE	256

/* privilege */
#define	PRIVILEGE_KRNL	0
#define	PRIVILEGE_TASK	1
#define	PRIVILEGE_USER	3
/* RPL */
#define	RPL_KRNL	SA_RPL0
#define	RPL_TASK	SA_RPL1
#define	RPL_USER	SA_RPL3

/* Process */
#define SENDING   0x02	/* set when proc trying to send */
#define RECEIVING 0x04	/* set when proc trying to recv */
#define WAITING   0x08	/* set when proc waiting for the child to terminate */
#define HANGING   0x10	/* set when proc exits without being waited by parent */
#define FREE_SLOT 0x20	/* set when proc table entry is not used
			 * (ok to allocated to a new process)
			 */

/* TTY */
#define	NR_CONSOLES	3	/* consoles */

/* 8259A interrupt controller ports. */
#define	INT_M_CTL	0x20 /* I/O port for interrupt controller         <Master> */
#define	INT_M_CTLMASK	0x21 /* setting bits in this port disables ints   <Master> */
#define	INT_S_CTL	0xA0 /* I/O port for second interrupt controller  <Slave>  */
#define	INT_S_CTLMASK	0xA1 /* setting bits in this port disables ints   <Slave>  */

/* 8253/8254 PIT (Programmable Interval Timer) */
#define	TIMER0          0x40 /* I/O port for timer channel 0 */
#define	TIMER_MODE      0x43 /* I/O port for timer mode control */
#define	RATE_GENERATOR	0x34 /* 00-11-010-0 :
			      * Counter0 - LSB then MSB - rate generator - binary
			      */
#define	TIMER_FREQ	1193182L/* clock frequency for timer in PC and AT */
#define	HZ		100	/* clock freq (software settable on IBM-PC) */

/* AT keyboard */
/* 8042 ports */
#define	KB_DATA		0x60	/* I/O port for keyboard data
				 *	Read : Read Output Buffer 
				 *	Write: Write Input Buffer
				 *             (8042 Data & 8048 Command)
				 */
#define	KB_CMD		0x64	/* I/O port for keyboard command
				 *	Read : Read Status Register
				 *	Write: Write Input Buffer
				 *	       (8042 Command)
				 */
#define	LED_CODE	0xED
#define	KB_ACK		0xFA

/* VGA */
#define	CRTC_ADDR_REG	0x3D4	/* CRT Controller Registers - Addr Register */
#define	CRTC_DATA_REG	0x3D5	/* CRT Controller Registers - Data Register */
#define	START_ADDR_H	0xC	/* reg index of video mem start addr (MSB) */
#define	START_ADDR_L	0xD	/* reg index of video mem start addr (LSB) */
#define	CURSOR_H	0xE	/* reg index of cursor position (MSB) */
#define	CURSOR_L	0xF	/* reg index of cursor position (LSB) */
#define	V_MEM_BASE	0xB8000	/* base of color video memory */
#define	V_MEM_SIZE	0x8000	/* 32K: B8000H -> BFFFFH */

/* CMOS */
#define CLK_ELE		0x70	/* CMOS RAM address register port (write only)
				 * Bit 7 = 1  NMI disable
				 *	   0  NMI enable
				 * Bits 6-0 = RAM address
				 */

#define CLK_IO		0x71	/* CMOS RAM data register port (read/write) */

#define  YEAR             9	/* Clock register addresses in CMOS RAM	*/
#define  MONTH            8
#define  DAY              7
#define  HOUR             4
#define  MINUTE           2
#define  SECOND           0
#define  CLK_STATUS    0x0B	/* Status register B: RTC configuration	*/
#define  CLK_HEALTH    0x0E	/* Diagnostic status: (should be set by Power
				 * On Self-Test [POST])
				 * Bit  7 = RTC lost power
				 *	6 = Checksum (for addr 0x10-0x2d) bad
				 *	5 = Config. Info. bad at POST
				 *	4 = Mem. size error at POST
				 *	3 = I/O board failed initialization
				 *	2 = CMOS time invalid
				 *    1-0 =    reserved
				 */

/* BIOS hard disk parameter vectors. */
#define	HD_0_PARM_VEC	0x41
#define	HD_1_PARM_VEC	0x46

/* Hardware interrupts */
#define	NR_IRQ		16	/* Number of IRQs */
#define	CLOCK_IRQ	0
#define	KEYBOARD_IRQ	1
#define	CASCADE_IRQ	2	/* cascade enable for 2nd AT controller */
#define	ETHER_IRQ	3	/* default ethernet interrupt vector */
#define	SECONDARY_IRQ	3	/* RS232 interrupt vector for port 2 */
#define	RS232_IRQ	4	/* RS232 interrupt vector for port 1 */
#define	XT_WINI_IRQ	5	/* xt winchester */
#define	FLOPPY_IRQ	6	/* floppy disk */
#define	PRINTER_IRQ	7
#define	AT_WINI_IRQ	14	/* at winchester */

/* Hard Drive */
#define SECTOR_SIZE		512
#define SECTOR_BITS		(SECTOR_SIZE * 8)
#define SECTOR_SIZE_SHIFT	9

/* tasks */
/* 注意 TASK_XXX 的定义要与 global.c 中对应 */
#define	INVALID_DRIVER	-20
#define	INTERRUPT	-10
#define TASK_TTY	0
#define TASK_SYS	1
#define TASK_HD		2
#define TASK_FS		3
#define TASK_MM		4
#define INIT		5
#define ANY		(NR_TASKS + NR_PROCS + 10)
#define NO_TASK		(NR_TASKS + NR_PROCS + 20)

#define	MAX_TICKS	0x7FFFABCD

/* system call */
#define	NR_SYS_CALL	2

/**
 * @enum msgtype
 * @brief MESSAGE types
 */
enum msgtype {
	/* 
	 * when hard interrupt occurs, a msg (with type==HARD_INT) will
	 * be sent to some tasks
	 */
	HARD_INT = 1,

	/* SYS task */
	GET_TICKS, GET_PID, GET_RTC_TIME, SYS_TEST,

	/* TTY */
	TTY_WRITE,

	/* FS */
	OPEN, CLOSE, READ, WRITE, LSEEK, STAT, UNLINK,

	/* FS & TTY */
	SUSPEND_PROC, RESUME_PROC,

	/* MM */
	EXEC, WAIT,

	/* FS & MM */
	FORK, EXIT,

	/* TTY, SYS, FS, MM, etc */
	SYSCALL_RET,

	/* message type for drivers */
	DEV_OPEN = 1001,
	DEV_CLOSE,
	DEV_READ,
	DEV_WRITE,
	DEV_IOCTL,
};

/* macros for messages */
#define	FD		u.m3.m3i1
#define	PATHNAME	u.m3.m3p1
#define	FLAGS		u.m3.m3i1
#define	NAME_LEN	u.m3.m3i2
#define	BUF_LEN		u.m3.m3i3
#define	CNT		u.m3.m3i2
#define	REQUEST		u.m3.m3i2
#define	PROC_NR		u.m3.m3i3
#define	DEVICE		u.m3.m3i4
#define	POSITION	u.m3.m3l1
#define	BUF		u.m3.m3p2
#define	OFFSET		u.m3.m3i2
#define	WHENCE		u.m3.m3i3

#define	PID		u.m3.m3i2
#define	RETVAL		u.m3.m3i1
#define	STATUS		u.m3.m3i1
/* 
    _____________________________________________________

                   +-----------------+
                   |     MESSAGE     |
                   +------+----------+
                   | type :   OPEN   |
                   +------+----------+
                   | PATHNAME        | u.m3.m3p1
                   +-----------------+
                   | FLAGS           | u.m3.m3i1
                   +-----------------+
                   | NAME_LEN        | u.m3.m3i2
                   +-----------------+
       USER_PROC -----------------------> FS
    _____________________________________________________

                   +-----------------+
                   |     MESSAGE     |
                   +------+----------+
                   | type :   READ   |
                   |      :or WRITE  |
                   +------+----------+
                   | FD              | u.m3.m3i1
                   +-----------------+
                   | BUF             | u.m3.m3p2
                   +-----------------+
                   | CNT             | u.m3.m3i2
                   +-----------------+
       USER_PROC -----------------------> FS
    _____________________________________________________

                   +-----------------+
                   |     MESSAGE     |
                   +------+----------+
                   | type :  LSEEK   |
                   +------+----------+
                   | FD              | u.m3.m3i1
                   +-----------------+
                   | OFFSET          | u.m3.m3i2
                   +-----------------+
                   | WHENCE          | u.m3.m3i3
                   +-----------------+
       USER_PROC -----------------------> FS
    _____________________________________________________
       
                   +-------------------+                                     
                   |      MESSAGE      |		                    
                   +------+------------+		                    +-------------------+                
                   | type :   DEV_READ |		                    |      MESSAGE      |		 
                   |      :or DEV_WRITE|		                    +------+------------+		 
                   +------+------------+		                    | type :   DEV_READ |		 
                   | DEVICE            | u.m3.m3i4	                    |      :or DEV_WRITE|		 
                   +-------------------+		                    +------+------------+		 
                   | POSITION          | u.m3.m3l1	                    | DEVICE            | u.m3.m3i4	 
                   +-------------------+		                    +-------------------+		 
                   | BUF               | u.m3.m3p2	                    | BUF               | u.m3.m3p2	 
                   +-------------------+		                    +-------------------+		 
                   | CNT               | u.m3.m3i2	                    | CNT               | u.m3.m3i2	 
                   +-------------------+		                    +-------------------+		 
                   | PROC_NR           | u.m3.m3i3	                    | PROC_NR           | u.m3.m3i3	 
                   +-------------------+		                    +-------------------+		 
              FS -------------------------> HD		               FS -------------------------> TTY	 
    _____________________________________________________    _____________________________________________________

       
                   +-------------------+                 
                   |      MESSAGE      |
                   +------+------------+
                   | type :  DEV_IOCTL |
                   +------+------------+
                   | DEVICE            | u.m3.m3i4
                   +-------------------+
                   | REQUEST           | u.m3.m3i2
                   +-------------------+
                   | BUF               | u.m3.m3p2
                   +-------------------+
                   | PROC_NR           | u.m3.m3i3
                   +-------------------+
              FS -------------------------> HD
    _____________________________________________________

       
                   +-------------------+                 
                   |      MESSAGE      |
                   +------+------------+
                   | type :    FORK    |
                   +------+------------+
       USER_PROC -----------------------> MM
    _____________________________________________________

       
                   +-------------------+                 
                   |      MESSAGE      |
                   +------+------------+
                   | type :    EXIT    |
                   +------+------------+
                   | STATUS            | u.m3.m3i1
                   +-------------------+
       USER_PROC -----------------------> MM
    _____________________________________________________

       
                   +-------------------+                 
                   |      MESSAGE      |
                   +------+------------+
                   | type :    EXEC    |
                   +------+------------+
                   | PATHNAME          | u.m3.m3p1
                   +-------------------+
                   | BUF               | u.m3.m3p2
                   +-------------------+
                   | NAME_LEN          | u.m3.m3i2
                   +-------------------+
                   | BUF_LEN           | u.m3.m3i3
                   +-------------------+
       USER_PROC -----------------------> MM
    _____________________________________________________
 */

#define	DIOCTL_GET_GEO	1

/* ipc */
#define SEND		1
#define RECEIVE		2
#define BOTH		3	/* BOTH = (SEND | RECEIVE) */

/* FS */
/*
	illustration of minor device number:

                             / drive 0:
                             | +---------------------------------------------------------------------------------------------------------------+   \
                             | |                                       hd0  ← device name           /the same\                                |   |
                             | |                                        0   ← minor device number   \ below  /                                |   | prim_dev: hd[0-5]
                             | +---------------------------------------------------------------------------------------------------------------+   |
                             | |            hd1            |            hd2            |            hd3            |            hd4            | ←--- primary partitions
                             | |             1             |             2             |             3             |             4             |   |
                             | +---------------------------+---------------------------+---------------------------+---------------------------+   /
                             | | hd1a | hd1b |  ... | hd1p | hd2a | hd2b |  ... | hd2p | hd3a | hd3b |  ... | hd3p | hd4a | hd4b |  ... | hd4p |
                             | | 0x10 | 0x11 |  ... | 0x1F | 0x20 | 0x21 |  ... | 0x2F | 0x30 | 0x31 |  ... | 0x3F | 0x40 | 0x41 |  ... | 0x4F |
                             | +---------------------------+---------------------------+---------------------------+---------------------------+
                             | |  ↑                       |←NR_SUB_PER_PARTITION:16→|                                                       |
                             | |  MINOR_hd1a:0x10          |  a, b, c, d,  e, f, g, h  |                                                       |
                             | |                           |  i, j, k, l,  m, n, o, p  |                                                       |
                             | |                                                                                                               |
                             | |←----------------------------------------- NR_PART_PER_DRIVE:  4 -------------------------------------------→|
                             | |←----------------------------------------- NR_SUB_PER_DRIVE : 64 -------------------------------------------→|
                             |                                                                                                                                            
                             |  struct hd_info::primary[0,1,2,3,4]    \
                             |                                         > the base and size of a drive/partition (in sectors)
                             |  struct hd_info::logical[0,1,2,...,63] /
                             |
	drives(MAX_DRIVES:2) |
                             |
                             |
                             | drive 1:
                             | +---------------------------------------------------------------------------------------------------------------+   \
                             | |                                                      hd5                                                      |   |
                             | |                                                       5                                                       |   | prim_dev: hd[5-9]
                             | +---------------------------------------------------------------------------------------------------------------+   |                       
                             | |             hd6           |            hd7            |            hd8            |            hd9            | ←--- primary partitions
                             | |              6            |             7             |             8             |             9             |   |
                             | +---------------------------+---------------------------+---------------------------+---------------------------+   /
                             | | hd6a | hd6b |  ... | hd6p | hd7a | hd7b |  ... | hd7p | hd8a | hd8b |  ... | hd8p | hd9a | hd9b |  ... | hd9p |
                             | | 0x50 | 0x51 |  ... | 0x5F | 0x60 | 0x61 |  ... | 0x6F | 0x70 | 0x71 |  ... | 0x7F | 0x80 | 0x81 |  ... | 0x8F |
                             \ +---------------------------+---------------------------+---------------------------+---------------------------+
                               |←----- partition 0 -----→|←----- partition 1 -----→|       ↗                  |←----- partition 3 -----→|
                                                                                             .`
                                                      .-------------------------------------`
                                                     |                                                                                                       
                                              e.g. how to calculate the minor device number of `hd8b':
                                                     hd8b: drive 1, partition 2, subpartion 1                                                             
                                                     device_number = MINOR_hd1a + NR_SUB_PER_DRIVE * drive + NR_SUB_PER_PARTITION * partition + subpartition       
                                                                   = 0x10       +             0x40 * drive +                 0x10 * partition + subpartition       
                                                                   = 0x10       +             0x40 * 1     +                 0x10 * 2         + 1                  
                                                                   = 0x10       +             0x40         +                 0x20             + 1                  
                                                                   = 0x71                                                                                    
                                              (drive, partion, subpartion : zero-based)
*/

/* major device numbers (corresponding to kernel/global.c::dd_map[]) */
#define	NO_DEV			0
#define	DEV_FLOPPY		1
#define	DEV_CDROM		2
#define	DEV_HD			3
#define	DEV_CHAR_TTY		4
#define	DEV_SCSI		5
/* make device number from major and minor numbers */
#define	MAJOR_SHIFT		8
#define	MAKE_DEV(a,b)		((a << MAJOR_SHIFT) | b)
/* separate major and minor numbers from device number */
#define	MAJOR(x)		((x >> MAJOR_SHIFT) & 0xFF)
#define	MINOR(x)		(x & 0xFF)

/* device numbers of hard disk */
#define	MINOR_hd1a		0x10
#define	MINOR_hd2a		0x20
#define	MINOR_hd2b		0x21
#define	MINOR_hd2c		0x22
#define	MINOR_hd3a		0x30
#define	MINOR_hd4a		0x40

#define	ROOT_DEV		MAKE_DEV(DEV_HD, MINOR_BOOT)	/* 3, 0x21 */

#define	INVALID_INODE		0
#define	ROOT_INODE		1

#define	MAX_DRIVES		2
#define	NR_PART_PER_DRIVE	4
#define	NR_SUB_PER_PART		16
#define	NR_SUB_PER_DRIVE	(NR_SUB_PER_PART * NR_PART_PER_DRIVE)
#define	NR_PRIM_PER_DRIVE	(NR_PART_PER_DRIVE + 1)

/**
 * @def MAX_PRIM
 * Defines the max minor number of the primary partitions.
 * If there are 2 disks, prim_dev ranges in hd[0-9], this macro will
 * equals 9.
 */
#define	MAX_PRIM		(MAX_DRIVES * NR_PRIM_PER_DRIVE - 1)

#define	MAX_SUBPARTITIONS	(NR_SUB_PER_DRIVE * MAX_DRIVES)

#define	P_PRIMARY	0
#define	P_EXTENDED	1

#define ORANGES_PART	0x99	/* Orange'S partition */
#define NO_PART		0x00	/* unused entry */
#define EXT_PART	0x05	/* extended partition */

#define	NR_FILES	64
#define	NR_FILE_DESC	64	/* FIXME */
#define	NR_INODE	64	/* FIXME */
#define	NR_SUPER_BLOCK	8


/* INODE::i_mode (octal, lower 12 bits reserved) */
#define I_TYPE_MASK     0170000
#define I_REGULAR       0100000
#define I_BLOCK_SPECIAL 0060000
#define I_DIRECTORY     0040000
#define I_CHAR_SPECIAL  0020000
#define I_NAMED_PIPE	0010000

#define	is_special(m)	((((m) & I_TYPE_MASK) == I_BLOCK_SPECIAL) ||	\
			 (((m) & I_TYPE_MASK) == I_CHAR_SPECIAL))

#define	NR_DEFAULT_FILE_SECTS	2048 /* 2048 * 512 = 1MB */


#endif /* _ORANGES_CONST_H_ */
